package com.xhwl.centiotdata.handler.eesd.impl;

import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.constant.EesdConstant;
import com.xhwl.centiotdata.handler.eesd.EesdFactory;
import com.xhwl.centiotdata.handler.eesd.EesdHandler;
import com.xhwl.centiotdata.pojo.enums.eesd.EesdMethodEnum;
import com.xhwl.centiotdata.service.cent.IBiEnvCentService;
import com.xhwl.centiotdata.suppliersystem.eesd.qiming.QiMingApiHandler;
import com.xhwl.centiotdata.suppliersystem.eesd.qiming.QiMingUtil;
import com.xhwl.centiotdata.utils.RedisUtils;
import com.xhwl.centiotdata.utils.ThreadPoolExecutorService;
import com.xhwl.common.dto.cent.bi.OdsChargeMetricsDTO;
import com.xhwl.common.dto.cent.iotdata.ev.CallChargeConnectorStatusReqDTO;
import com.xhwl.common.dto.cent.iotdata.ev.CallChargeOrderReqDTO;
import com.xhwl.common.dto.cent.iotdata.ev.ChargeConfigDTO;
import com.xhwl.common.pojo.cent.device.DeviceProjSupplierCategory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * @Author： lianghz
 * @Description：
 * @Date 2021/09/06/ 11:31
 */
@Slf4j
@Service
public class EesdQiMingHandler extends EesdHandler {

    @Resource
    private QiMingApiHandler qiMingApiHandler;
    @Resource
    private IBiEnvCentService biEnvCentService;
    @Resource
    private QiMingUtil qiMingUtil;
    @Resource
    private RedisUtils redisUtils;

    private static final String CONFIG = "qiming:config:";

    /**
     * id:产品id，来源cent_device库中device_product表中的数据
     */
    @Override
    public void afterPropertiesSet() {
        EesdFactory.register(EesdMethodEnum.QI_MING.getId(), this);
    }

    /**
     * todo 改为推送
     * 同步充电站、充电设备、充电设备接口信息
     * @param config
     */
    @Override
    public void pullCharge(DeviceProjSupplierCategory config) {
        String key = CONFIG + config.getProjectId();
        redisUtils.set(key, config);
        try {
            List<OdsChargeMetricsDTO> list = new ArrayList<>();
            List<OdsChargeMetricsDTO> list1 = null;
            try {
                list1 = qiMingApiHandler.pullStationInfo(config);
            } catch (Exception e) {
                log.error("充电桩-站数据 失败： {}", e.getMessage());
            }
            List<OdsChargeMetricsDTO> list2 = null;
            try {
                list2 = qiMingApiHandler.pullChargeStats(config);
            } catch (Exception e) {
                log.error("充电桩-统计数据 失败： {}", e.getMessage());
            }
            List<OdsChargeMetricsDTO> list3 = null;
            try {
                list3 = qiMingApiHandler.pullChargeStatus(config);
            } catch (Exception e) {
                log.error("充电桩-状态数据 失败： {}", e.getMessage());
            }
            if (!CollectionUtils.isEmpty(list1)) {
                list.addAll(list1);
            }
            if (!CollectionUtils.isEmpty(list2)) {
                list.addAll(list2);
            }
            if (!CollectionUtils.isEmpty(list3)) {
                list.addAll(list3);
            }
            if (!CollectionUtils.isEmpty(list)) {
                String dataStr = JSONObject.toJSONString(list);
                log.info("充电桩数据 开始： {}", dataStr);
                biEnvCentService.asyncChargeInfo(dataStr);
            }
        } catch (Exception e) {
            log.error("充电桩数据 失败： {}",  e.getMessage());
        }
    }

    /**
     * 统计充电桩订单相关数据（1h调度一次）
     */
    @Override
    public void statisticsCharge(DeviceProjSupplierCategory config) {
        Integer projectId = config.getProjectId();
        log.info("统计充电桩订单相关数据 开始： {}", projectId);
        biEnvCentService.asyncStatisticsCharge(projectId);
    }



    /*************************************************回调接口***************************************************/

    /**
     * 南投推送正式环境
     */
    private final static String SECRET = "1234567890abcdef";
    private final static String OPERATOR_ID = "017163882";
    private final static String HOST = "https://ccyd.tiantianchong.cn/evcs/v257";
    private final static String QUERY_TOKEN = "/query_token";

    @Override
    public JSONObject queryToken(JSONObject dto) {
        ChargeConfigDTO config = new ChargeConfigDTO();
        config.setOperatorId(OPERATOR_ID);
        config.setSecret(SECRET);
        config.setHost(HOST);
        config.setTokenUrl(QUERY_TOKEN);

        log.info("充电桩 回调请求参数: {}", dto);
        // 推送过来的数据
        String dataResp = dto.getString("Data");
        String resultData = qiMingUtil.decryptData(dataResp, config);
        JSONObject jsonResp = JSONObject.parseObject(resultData);
        String operatorID = jsonResp.getString("OperatorID");
        JSONObject allToken = qiMingUtil.getAllToken(config);

        String operatorIDOld = allToken.getString("OperatorID");
        String accessToken = allToken.getString("AccessToken");
        String tokenAvailableTime = allToken.getString("TokenAvailableTime");
        Integer failReason;
        Integer succStat;
        if (operatorID.equals(operatorIDOld)) {
            failReason = allToken.getInteger("FailReason");
            succStat = allToken.getInteger("SuccStat");
        } else {
            failReason = EesdConstant.NUM_1;
            succStat = EesdConstant.NUM_1;
        }
        //log.info("回调参数解析data: {}", allToken);
        // 构造data参数
        JSONObject obj = new JSONObject();
        obj.put("OperatorID", operatorID);
        obj.put("SuccStat", succStat);
        obj.put("AccessToken", accessToken);
        obj.put("FailReason", failReason);
        obj.put("TokenAvailableTime", tokenAvailableTime);
        String msg = "南投-获取鉴权成功";
        return makeResp(obj.toJSONString(), msg);
    }

    /**
     * 统计需要通过充电订单账单来统计
     * @param dto
     * @return
     */
    @Override
    public JSONObject callChargeOrder(JSONObject dto) {
        ChargeConfigDTO config = new ChargeConfigDTO();
        config.setOperatorId(OPERATOR_ID);
        config.setSecret(SECRET);
        config.setHost(HOST);
        config.setTokenUrl(QUERY_TOKEN);
        config.setProjectId(2);

        CallChargeOrderReqDTO resultDTO = makeReq(dto, config);
        asyncChargeOrder(JSONObject.toJSONString(resultDTO));
        // 构造data参数
        JSONObject obj = new JSONObject();
        obj.put("StartChargeSeq", resultDTO.getStartChargeSeq());
        obj.put("ConnectorID", resultDTO.getConnectorID());
        obj.put("ConfirmResult", 0);
        String msg = "南投-推送推送充电账单成功";
        return makeResp(obj.toJSONString(), msg);
    }

    /**
     * 异步同步订单信息
     * @param parm 为json格式字符串
     */
    private void asyncChargeOrder(String parm) {
        CompletableFuture.runAsync(()->{
            try {
                log.info("异步同步订单信息:{}", parm);
                biEnvCentService.asyncChargeOrder(parm);
            } catch (Exception e) {
                log.info("异步执行操作：失败 {}", e.getMessage());
            }
            log.info("异步执行操作，结束");
        }, ThreadPoolExecutorService.getThreadPool());
    }

    /**
     * 解析回调请求
     * @param dto 回调请求参数
     * @return
     */
    private CallChargeOrderReqDTO makeReq(JSONObject dto, ChargeConfigDTO config) {
        log.info("充电桩回调请求参数: {}", dto);
        // 推送过来的数据
        String dataResp = dto.getString("Data");
        String resultData = qiMingUtil.decryptData(dataResp, config);
        CallChargeOrderReqDTO resultDTO = JSONObject.parseObject(resultData, CallChargeOrderReqDTO.class);
        resultDTO.setProjectId(config.getProjectId());
        String startChargeSeq = resultDTO.getStartChargeSeq();
        String key = config.getProjectId() + ":" + startChargeSeq;

        redisUtils.setWithMinute(key, resultDTO, EesdConstant.FIVE_HOUR);
        log.info("充电桩-回调参数解析data: {}", JSONObject.toJSONString(resultDTO));
        return resultDTO;
    }

    /**
     * 构造回调响应
     * @param parm
     */
    private JSONObject makeResp(String parm, String msg) {
        ChargeConfigDTO config = new ChargeConfigDTO();
        config.setOperatorId(OPERATOR_ID);
        config.setSecret(SECRET);
        config.setHost(HOST);
        config.setTokenUrl(QUERY_TOKEN);

        String reqParam = qiMingUtil.buildReqParam(parm, config);
        JSONObject jsonObject = JSONObject.parseObject(reqParam);
        String data = jsonObject.getString("Data");
        String sig = jsonObject.getString("Sig");
        // 构造响应
        JSONObject resp = new JSONObject();
        resp.put("Ret", EesdConstant.NUM_0);
        resp.put("Msg", msg);
        resp.put("Sig", sig);
        resp.put("Data", data);
        log.info("回调响应参数：{}",JSONObject.toJSONString(resp));
        return resp;
    }

    /**
     * 推送枪状态
     * @param dto
     * @return
     */
    public JSONObject callStationStatus(JSONObject dto) {
        ChargeConfigDTO config = new ChargeConfigDTO();
        config.setOperatorId(OPERATOR_ID);
        config.setSecret(SECRET);
        config.setHost(HOST);
        config.setTokenUrl(QUERY_TOKEN);
        config.setProjectId(2);

        CallChargeConnectorStatusReqDTO result = makeStatusReq(dto, config);

        OdsChargeMetricsDTO odsChargeMetricsDTO = new OdsChargeMetricsDTO();
        odsChargeMetricsDTO.setProjectId(2);
        odsChargeMetricsDTO.setConnectorId(result.ConnectorID);
        odsChargeMetricsDTO.setConnectorStatus(result.getStatus());

        asyncStationStatus(JSONObject.toJSONString(odsChargeMetricsDTO));

        // 构造data参数
        JSONObject obj = new JSONObject();
        obj.put("status", 0);
        String msg = "充电桩-推送设备状态变化成功";
        return makeResp(obj.toJSONString(), msg);
    }

    /**
     * 解析设备状态变化回调请求
     * @param dto 回调请求参数
     * @return
     */
    private CallChargeConnectorStatusReqDTO makeStatusReq(JSONObject dto, ChargeConfigDTO config) {
        // 推送过来的数据
        String dataResp = dto.getString("Data");
        String resultData = qiMingUtil.decryptData(dataResp, config);
        JSONObject jsonObject = JSONObject.parseObject(resultData);
        String connectorStatusInfo = jsonObject.getString("ConnectorStatusInfo");
        CallChargeConnectorStatusReqDTO resultDTO = JSONObject.parseObject(connectorStatusInfo, CallChargeConnectorStatusReqDTO.class);
        resultDTO.setProjectId(config.getProjectId());
        log.info("充电桩-解析设备状态变化回调解析data: {}", JSONObject.toJSONString(resultDTO));
        return resultDTO;
    }

    /**
     *
     * CallChargeOrderReqDTO resultDTO = makeReq(dto, config);
     * asyncChargeOrder(JSONObject.toJSONString(resultDTO));
     * 异步同步订单信息
     * @param parm 为json格式字符串
     */
    private void asyncStationStatus(String parm) {
        CompletableFuture.runAsync(()->{
            try {
                log.info("充电桩异步设备状态:{}", parm);
                biEnvCentService.asyncChargeStatus(parm);
            } catch (Exception e) {
                log.info("充电桩异步设备状态执行操作：失败 {}", e.getMessage());
            }
            log.info("异步执行操作，结束");
        }, ThreadPoolExecutorService.getThreadPool());
    }

}
